package com.parsec.sb.util;

import cn.hutool.core.util.EnumUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;

import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * 凯桥枚举工具类
 * <p>
 * 作为{@link cn.hutool.core.util.EnumUtil}工具类的补充，添加了一部分方便凯桥信息使用的枚举工具类
 * 约定：如果自定义枚举中使用了 code,desc 字段，可以更简洁的调用一下方法：
 * {@link #getDescByCode(Class, String)}
 * {@link #getEnumByCode(Class, String)}
 * 方便业务场景中的枚举字段格式化，取枚举中任意值等操作。
 * </p>
 *
 * @author xujiahong since 2021-07-01
 */
public class KqEnumUtil {

    public static <E extends Enum<E>> String getDescByCode(Class<E> clazz, String code) {
        return KqEnumUtil.getFiled2ByFiled1(clazz, code, "code", "desc");
    }

    public static <E extends Enum<E>> E getEnumByCode(Class<E> clazz, String code) {
        return KqEnumUtil.getEnumByField(clazz, "code", code);
    }

    public static <E extends Enum<E>> String getFiled2ByFiled1(Class<E> clazz, String fieldValue, String filed1, String filed2) {
        try {
            //[null, null, null, null, null, null]
            List<Object> codeList = EnumUtil.getFieldValues(clazz, filed1);
            List<Object> descList = EnumUtil.getFieldValues(clazz, filed2);
            for (int i = 0; i < codeList.size(); i++) {
                Object code = codeList.get(i);
                Object desc = descList.get(i);
                if (code == null || desc == null) {
                    return fieldValue;
                }
                if (fieldValue.equals(code.toString())) {
                    return desc.toString();
                }
            }
            return fieldValue;
        } catch (Exception e) {
            return fieldValue;
        }
    }

    public static <E extends Enum<E>> E getEnumByField(Class<E> clazz, String fieldName, String fieldValue) {
        try {
            Map<String, Object> nameFieldMap = EnumUtil.getNameFieldMap(clazz, fieldName);
            Map<String, E> nameEnumMap = EnumUtil.getEnumMap(clazz);
            Optional<String> first = nameFieldMap.keySet().stream().filter(name -> nameFieldMap.get(name) != null &&
                    fieldValue.equals(nameFieldMap.get(name).toString())).findFirst();
            return first.map(nameEnumMap::get).orElse(null);
        } catch (Exception e) {
            //避免了fieldName不存在时引发的空指针异常
            return null;
        }
    }

    @Getter
    @AllArgsConstructor
    public enum TestEnum {
        TEST1("type1", "code1", "desc1"),
        TEST2("type2", "code2", "desc2"),
        TEST3("type3", "code3", "desc3"),
        TEST4("type4", "code4", "desc4"),
        TEST5("type5", "code5", "desc5"),
        TEST6("type6", "code6", "desc6");

        private final String type;
        private final String code;
        private final String desc;
    }

    public static void main(String[] args) {
        //test getDescByCode
        for (int i = 1; i <= 6; i++) {
            assert ("desc" + i).equals(KqEnumUtil.getDescByCode(TestEnum.class, "code" + i));
        }
        assert "notExist".equals(KqEnumUtil.getDescByCode(TestEnum.class, "notExist"));
        //test getFiled2ByFiled1
        String[] filed1Array = {"type", "type", "code", "code", "desc", "desc"};
        String[] filed2Array = {"code", "desc", "type", "desc", "type", "code"};
        for (int i = 0; i < 6; i++) {
            String filed1 = filed1Array[i];
            String filed2 = filed2Array[i];
            for (int j = i; j <= 6; j++) {
                String value1 = filed1 + j;
                String value2 = filed2 + j;
                assert value2.equals(KqEnumUtil.getFiled2ByFiled1(TestEnum.class, value1, filed1, filed2));
            }
        }
        assert "notExist".equals(KqEnumUtil.getFiled2ByFiled1(TestEnum.class, "notExist", "code", "desc"));
        assert "notExist".equals(KqEnumUtil.getFiled2ByFiled1(TestEnum.class, "code1", "notExist", "desc"));
        assert "notExist".equals(KqEnumUtil.getFiled2ByFiled1(TestEnum.class, "code1", "code", "notExist"));
        //test getEnumByField
        assert TestEnum.TEST1.equals(KqEnumUtil.getEnumByField(TestEnum.class, "code", "code1"));
        assert TestEnum.TEST1.equals(KqEnumUtil.getEnumByField(TestEnum.class, "desc", "desc1"));
        assert TestEnum.TEST1.equals(KqEnumUtil.getEnumByField(TestEnum.class, "type", "type1"));
        assert TestEnum.TEST3.equals(KqEnumUtil.getEnumByField(TestEnum.class, "code", "code3"));
        assert TestEnum.TEST3.equals(KqEnumUtil.getEnumByField(TestEnum.class, "desc", "desc3"));
        assert TestEnum.TEST3.equals(KqEnumUtil.getEnumByField(TestEnum.class, "type", "type3"));
        assert KqEnumUtil.getEnumByField(TestEnum.class, "notExist", "code1") == null;
        assert KqEnumUtil.getEnumByField(TestEnum.class, "code", "notExist") == null;
        System.out.println("=======================测试通过=======================");
    }

}
